package com.gxc.string;

import com.gxc.print.ArrayPrint;
import com.gxc.print.ListPrint;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Stack;

/**
 71. 简化路径
 给你一个字符串 path ，表示指向某一文件或目录的 Unix 风格 绝对路径 （以 '/' 开头），
 请你将其转化为 更加简洁的规范路径。

 在 Unix 风格的文件系统中规则如下：

 一个点 '.' 表示当前目录本身。
 此外，两个点 '..' 表示将目录切换到上一级（指向父目录）。
 任意多个连续的斜杠（即，'//' 或 '///'）都被视为单个斜杠 '/'。
 任何其他格式的点（例如，'...' 或 '....'）均被视为有效的文件/目录名称。
 返回的 简化路径 必须遵循下述格式：

 始终以斜杠 '/' 开头。
 两个目录名之间必须只有一个斜杠 '/' 。
 最后一个目录名（如果存在）不能 以 '/' 结尾。
 此外，路径仅包含从根目录到目标文件或目录的路径上的目录（即，不含 '.' 或 '..'）。
 返回简化后得到的 规范路径 。
 */
public class SimplifyPath {

    public static void main(String[] args) {
        /*System.out.println(handle("/home/"));
        System.out.println(handle("/home//foo/"));
        System.out.println(handle("/home/user/Documents/../Pictures"));
        System.out.println(handle("/../"));
        System.out.println(handle("/.../a/../b/c/../d/./"));*/
        System.out.println(handle("/a//b////c/d//././/.."));

        ArrayPrint.print3("/a//b////c/d//././/..".split("/"));
    }

    public static String handle(String path) {
        char[] charArray = path.toCharArray();
        int length = charArray.length;
        int index = 0;
        Stack<Character> stack = new Stack<>();
        stack.push('/');
        //连续 . 的数量
        int num = 0;
        while (index < length) {
            char c = charArray[index];
            if (c == '/') {
                processPoint(stack, num);
                num = 0;
                if (stack.peek() == '/') {
                    index++;
                    continue;
                }
            } else if (c == '.'){
                if (stack.peek() == '/') num++;
                else if (num>0) {
                    num++;
                }
            } else {
                num = 0;
            }
            stack.push(c);
            index++;
        }
        // ***/..  处理这种形势
        processPoint(stack, num);
        if (stack.size() > 1 && stack.peek() == '/') stack.pop();

        StringBuffer buffer = new StringBuffer();
        while (!stack.isEmpty()) buffer.append(stack.pop());
        return buffer.reverse().toString();
    }

    private static void processPoint(Stack<Character> stack, int num) {
        if (num >2 || num==0) return;
        if (num == 1) {
            //   **/./**  形式
            stack.pop();
        } else {
            //   **/../**  形式
            stack.pop();
            stack.pop();
            if (stack.size() == 1) return;
            stack.pop();
            while (stack.peek() != '/') stack.pop();
        }
    }

    class Solution {
        public String simplifyPath(String path) {
            Deque<String> stack = new LinkedList<>();

            String[] arrays = path.split("/");
            for (String name : arrays) {
                if ("..".equals(name)) {
                    if (!stack.isEmpty()) stack.pollLast();
                } else if (name.length() > 0 && !".".equals(name)) {
                    stack.offer(name);
                }
            }

            StringBuilder builder = new StringBuilder();
            if (stack.isEmpty()) {
                builder.append("/");
            } else {
                while (!stack.isEmpty()) {
                    builder.append("/").append(stack.pop());
                }
            }
            return builder.toString();
        }
    }

}
